package com.safeluck.floatwindow;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.telecom.Call;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

import com.anyun.libusbcamera.UsbCamera;
import com.google.gson.Gson;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.CsvFormatStrategy;
import com.orhanobut.logger.DiskLogAdapter;
import com.orhanobut.logger.FormatStrategy;
import com.orhanobut.logger.Logger;
import com.orhanobut.logger.PrettyFormatStrategy;

import com.safeluck.floatwindow.bean.GlobalData;
import com.safeluck.floatwindow.camera.CameraWrapper;
import com.safeluck.floatwindow.usbVideo.RecordParams;
import com.safeluck.floatwindow.usbVideo.UsbCameraVideo;
import com.safeluck.floatwindow.util.FileUtil;
import com.safeluck.floatwindow.util.MyLog;
import com.safeluck.floatwindow.util.SDCardHelper;
import com.safeluck.floatwindow.util.TimeUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


/**
 * aaa
 * Created by lzw on 2018/8/20. 14:16:54
 * 邮箱：632393724@qq.com
 * All Rights Saved! Chongqing AnYun Tech co. LTD
 */
public class FloatingService extends Service implements SurfaceHolder.Callback {
    private static final String TAG = FloatingService.class.getSimpleName();
    private static final int FINISH = 100;//stop media,主要是为了客户端调用的时候，不占用很长时间，在handleMsg里处理
    private static final int START = 101;//start media...
    public static String VIDEO_RECORD_SD_PATH = "/storage/emulated/0/AnYun_VIDEO";
    public static String VIDEO_RECORD_TFCard_PATH = "/storage/sdcard1/AnYun_VIDEO";

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == FINISH){
                onDestroy();
            }else if (msg.what == START){
                InitStartMedia();
            }
        }
    };


    private MediaRecordCls mediaRecordCls;
    private WindowManager windowManager;
    WindowManager.LayoutParams layoutParams;
    SurfaceView button;
    private MediaArgu mediaArgu;

    private String waizhiPath;
    private SurfaceHolder surfaceHolder;
    public static boolean isActive = false;
    private boolean isUseTFCard = false;//是否使用外置tf卡，为false则表示使用内部flash

    private boolean isYourStop = false;//是用户主动点击的“结束”走OnDestroy 还是录像时间到走的OnDestroy；
    private int curErrorCode = 4;//用于标记UsbCamera录像的错误码，如果为4才是真正的结束要回调文件名和时长其他则不回调给客户
    private boolean usbCameraExist = false;

    private int  callbackTimeOut = 10;//对外回调超时时间，如果一直没有给对外结果，12s后主动给结束结果



    private String pathS;
    private void registBroadCastReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.safeluck.floatwindow.studyinfo");
        registerReceiver(mCloseBroadCastReceiver, filter);

    }
    private void unRegisterTestBroadReceiver() {
        if (mCloseBroadCastReceiver != null) {

            //查询到相应的BroadcastReceiver
            unregisterReceiver(mCloseBroadCastReceiver);

        }
    }

    private BroadcastReceiver mCloseBroadCastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals("com.safeluck.floatwindow.studyinfo")) {
                String str=  intent.getStringExtra("info");
                Log.i(TAG, "广播"+str);
                GlobalData.getInstance().setWaterMaskInfo(str);
            }
        }
    };

    private Runnable callBackTimeOutRun = new Runnable() {
        @Override
        public void run() {
            Log.i(TAG, "12s时间到，主动触发对外通知");
            callback(1, 2, "长时间断网");
            onDestroy();
        }
    };

    final RemoteCallbackList<IMyCallback> mcallbacks = new RemoteCallbackList<>();

    IMediaAidlInterface.Stub stub = new IMediaAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

//        @Override
//        public void transferInfo(String info) throws RemoteException {
//            GlobalData.getInstance().setWaterMaskInfo(info);
//        }

        @Override
        public void startMedia(final MediaArgu media) throws RemoteException {
            MyLog.i(TAG, "startMedia(first stop): MediaArgu=" + media.toString());
            MyLog.i(TAG,"注册水印广播");
            registBroadCastReceiver();
//            if (handler.hasMessages(START)){
//                handler.removeMessages(START);
//            }
            mediaArgu = media;
            GlobalData.getInstance().setMediaArgu(mediaArgu);
//            Message message = Message.obtain();
//            message.what = START;
//            handler.sendMessage(message);


            if (handler.hasMessages(FINISH)){
                handler.removeMessages(FINISH);
            }
            handler.postDelayed(callBackTimeOutRun,callbackTimeOut*1000);
            Message message = Message.obtain();
            message.what = FINISH;
            handler.sendMessage(message);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    InitStartMedia();
                }
            });

        }

        @Override
        public void stopMedia() throws RemoteException {

            MyLog.i(TAG, "stopMedia: ");
            if (handler.hasMessages(FINISH)){
                handler.removeMessages(FINISH);
            }
            Message message = Message.obtain();
            message.what = FINISH;
            handler.sendMessage(message);

        }

        @Override
        public void registerCallback(IMyCallback cb) throws RemoteException {
            if (cb != null) {
                mcallbacks.register(cb);
            }
        }

        @Override
        public void unregisterCallback(IMyCallback cb) throws RemoteException {
            if (cb != null) {
                mcallbacks.unregister(cb);
            }
        }
    };

    private void InitStartMedia() {
        if (mediaArgu.isPush()) {
            if (mediaArgu.isUsedOutCamera()){
                MyLog.i(TAG, "run: 用USBCamera进行推流");
                boolean result = AliSdkMgr.getInstance(getApplicationContext()).checkUsbCameraExist();
                if (!result){
                    callback(1,-1,"usbCamera打不开");
                    AliSdkMgr.getInstance(getApplicationContext()).destroyAliSdk();
                    FloatingService.this.stopSelf();
                }else{
                    init();
                }
            }else{
                MyLog.i(TAG, "run: 用DevCamera进行推流");
                init();
            }
        } else {
            //检查usbcamera是否存在
//            boolean result = AliSdkMgr.getInstance(getApplicationContext()).checkUsbCameraExist();
            AliSdkMgr.getInstance(getApplicationContext()).checkUsbCameraExist();

            List<String> paths = SDCardHelper.getExtSDCardPathList();
            isUseTFCard = mediaArgu.getTfCardFlag()==1?true:false;
            if (!isUseTFCard){
                pathS = Environment.getExternalStorageDirectory().getAbsolutePath();


                waizhiPath = pathS+"/AnYun_VIDEO";
                FileUtil.createFile(waizhiPath, "2.txt");
                double size = SDCardHelper.getFileOrFilesSize(waizhiPath,SDCardHelper.SIZETYPE_MB);
                MyLog.i(TAG,"AnYun_video.size="+size);
                long avaliablesize= SDCardHelper.getSDCardAvailableSize();
                MyLog.i(TAG,String.format("SD卡可用空间=%d",avaliablesize));
                if (avaliablesize<1000){
                    MyLog.i(TAG,"SD卡可用空间小于1000MB,实际可用="+avaliablesize);
                    if (size>avaliablesize){
                        SDCardHelper.sortFilesByLastModified(this.getApplicationContext(),waizhiPath,2);

                    }
                }else{
                    while (size>1000.0f){
                        SDCardHelper.sortFilesByLastModified(this.getApplicationContext(),waizhiPath,2);
                        size =  SDCardHelper.getFileOrFilesSize(Environment.getExternalStorageDirectory().getAbsolutePath()+
                                File.separator+"AnYun_VIDEO",SDCardHelper.SIZETYPE_MB);
                    }
                }

            }else{
                for (String path :
                        paths) {
                    if (path.contains("sdcard1")) {
                        Log.i(TAG, "init: sdcard1=" + path);
                        waizhiPath = path + "/AnYun_VIDEO";
                        FileUtil.createFile(waizhiPath, "2.txt");

                        break;
                    }
                }
            }


            MyLog.i(TAG,"录像存放目录"+waizhiPath);
            if (!TextUtils.isEmpty(waizhiPath)){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (SDCardHelper.getWaiZhiSDCardAvailableSize(waizhiPath)<1000){
                            MyLog.i(TAG,"删除录像目录下得文件");
                            SDCardHelper.sortFilesByLastModified(FloatingService.this.getApplicationContext(),waizhiPath,2);
                        }
                    }
                }).start();

                init();

            }else{
                MyLog.i(TAG, "run: 本地录像存放目录不存在");
                callback(0, 1, "没有外置sd卡");
                FloatingService.this.stopSelf();
            }

        }
    }


    void callback(int type, int err, String message) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setErrCode(err);
        responseVO.setType(type);
        JSONObject jsonObject = new JSONObject();

        MyLog.i(TAG,"type:"+type+" err:"+err+" msg:"+message);
        try {
            jsonObject.put("type",type);
            jsonObject.put("errCode",err);
            jsonObject.put("source",mediaArgu.isUsedOutCamera()?1:0);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (err == 0){
            // 带分辨率
            String[] resolutions = message.split(",");

            try {
                jsonObject.put("width",Integer.parseInt(resolutions[0]));
                jsonObject.put("height",Integer.parseInt(resolutions[1]));

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }else if (type==0 && (err ==4||err==5)){
            String[] resolutions = message.split(",");
            try {
                jsonObject.put("fileName",resolutions[0]);
                jsonObject.put("playTime",Integer.parseInt(resolutions[1]));

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }else{
            try {
                jsonObject.put("message",message);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        message = jsonObject.toString();
        responseVO.setMessage(message);


        final int N = mcallbacks.beginBroadcast();
        for (int i = 0; i < N; i++) {
            try {
                mcallbacks.getBroadcastItem(i).onResult(responseVO);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        mcallbacks.finishBroadcast();
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        return stub;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }

    public void init() {
        MyLog.i(TAG,BuildConfig.VERSION_CODE+" versionName="+BuildConfig.VERSION_NAME);
        if (!isActive) {
            MyLog.i(TAG, "onStartCommand: isActive");
//            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//            audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);

            showFloatingWindow();
            isActive = true;

        }


    }

    private void showFloatingWindow() {

        //先判断是否有悬浮窗权限
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            if (Settings.canDrawOverlays(this)) {
                MyLog.i(TAG, "showFloatingWindow: >=M");
                showwindow();
            }
        } else {
            MyLog.i(TAG, "showFloatingWindow: <M");
            showwindow();
        }

    }

    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public void surfaceCreated(final SurfaceHolder surfaceHolder) {
        this.surfaceHolder = surfaceHolder;


        MyLog.i(TAG, "surfaceCreated: ");
        if (mediaArgu.isPush()) {
            AliSdkMgr.getInstance(this).transferMediaArgu(mediaArgu);
            AliSdkMgr.getInstance(this).initSdk();
            AliSdkMgr.getInstance(this).setUIListener(new UICallBackListener() {
                @Override
                public void rtmpAddr(String url) {

                }

                @Override
                public void onNetworkPoor() {
                    callback(1, 3, "网络较差");
                    handler.removeCallbacks(callBackTimeOutRun);
                }

                @Override
                public void onConnectFail() {

                    callback(1, 2, "长时间断网");
                    if (handler.hasMessages(FINISH)){
                        handler.removeMessages(FINISH);
                    }
                    Message message = Message.obtain();
                    message.what = FINISH;
                    handler.sendMessage(message);

                }

                @Override
                public void onReconnectFail() {
                    callback(1, 2, "长时间断网");

                    if (handler.hasMessages(FINISH)){
                        handler.removeMessages(FINISH);
                    }
                    Message message = Message.obtain();
                    message.what = FINISH;
                    handler.sendMessage(message);
                }

                @Override
                public void onPushStarted(int width,int height) {
                    callback(1, 0, width+","+height);
                    handler.removeCallbacks(callBackTimeOutRun);
                }

                @Override
                public void onPushStoped(int code) {
                    String msg ;

                    if (code == -1){
                        msg = "UsbCamera打不开";
                    }else{
                        msg = "推流结束";
                    }
                    callback(1, code, msg);
                    MyLog.i(TAG, " 推流结束");
                    onDestroy();

                }


            });
            AliSdkMgr.getInstance(this).startPreviewAsync(button);

        } else {
            if (mediaArgu.isUsedOutCamera()) {
                MyLog.i("UsbCamera进行录像");
                UsbCameraVideo.getInstance().registerMediaListener(new UsbCameraVideo.MediaListener() {


                    @Override
                    public void start(int type, int errCode, String msg) {
                        callback(type,errCode,msg);
                    }

                    @Override
                    public void stop() {
                        //时间到主动结束 ，走完onDestroy会回调recordTime
                        MyLog.i("UsbCamera录像时间到");
                        isYourStop = true;
                        onDestroy();
                    }

                    @Override
                    public void openResult(int ret) {
                        if (ret == 0){
                            usbCameraExist = true;
                            MyLog.i("相机打开成功,UsbCamera开始录制");


                            final RecordParams params = new RecordParams();
                            params.setRecordPath(waizhiPath);
                            params.setRecordDuration(mediaArgu.getRecordTime());

                            UsbCameraVideo.getInstance().startRecord(params);

                        }else{
                            MyLog.i("相机打开失败,UsbCamera不录制");
                            usbCameraExist = false;
                            callback(0,ret,"UsbCamera打不开");
                            onDestroy();
                        }
                    }

                    @Override
                    public void recordTime(String fileName,int sec,int err) {
                        callback(0,err,fileName+","+sec);
                    }

                    @Override
                    public void ErrState(int errcode) {
                        callback(0,errcode,"SystemError");
                        MyLog.i("usbcamera录像SystemError"+errcode);
                        curErrorCode = errcode;
                        onDestroy();
                    }
                });

                Size resolution = null;
                if (mediaArgu.getM_screen() != null){
                    resolution = new Size(mediaArgu.getM_screen().width,mediaArgu.getM_screen().height);
                }
                UsbCameraVideo.getInstance().handleStartPreview(surfaceHolder, resolution);

            } else {
                /*
                if (mediaRecordCls != null)
                mediaRecordCls.starter(surfaceHolder, mediaArgu, waizhiPath, new MediaRecordCls.ServiceFinishListener() {
                    @Override
                    public void stopSelf() {
                        Log.i(TAG, "stopSelf: MediaRecorder");

                        onDestroy();


                    }

                    @Override
                    public void start() {
                        //通过devVidoeDur 回调出去告诉录像开始和分辨率
//                        callback(0, 0, "正在录像");
                    }

                    @Override
                    public void devCameraRes(Size size) {
                        callback(0,0,size.getWidth()+","+size.getHeight());
                    }

                    @Override
                    public void devVideoDur(int timeS,int errcode) {
                        callback(0,errcode,mediaRecordCls.getFILE_NAME()+","+String.valueOf(timeS));
                    }

                    @Override
                    public void badCamera(int i) {
                        callback(0,i,"设备相机打开异常");
                        onDestroy();//停掉录像
                    }
                });
                */


                initCamera(false);

                CameraWrapper.getInstance().registerMediaListener(new UsbCameraVideo.MediaListener() {


                    @Override
                    public void start(int type, int errCode, String msg) {
                        callback(type,errCode,msg);
                    }

                    @Override
                    public void stop() {
                        //时间到主动结束 ，走完onDestroy会回调recordTime
                        MyLog.i("UsbCamera录像时间到");
                        isYourStop = true;
                        onDestroy();
                    }

                    @Override
                    public void openResult(int ret) {
                        if (ret == 0){
                            usbCameraExist = true;
                            MyLog.i("相机打开成功,UsbCamera开始录制");


                            final RecordParams params = new RecordParams();
                            params.setRecordPath(waizhiPath);
                            params.setRecordDuration(mediaArgu.getRecordTime());

                            UsbCameraVideo.getInstance().startRecord(params);

                        }else{
                            MyLog.i("相机打开失败,UsbCamera不录制");
                            usbCameraExist = false;
                            callback(0,ret,"UsbCamera打不开");
                            onDestroy();
                        }
                    }

                    @Override
                    public void recordTime(String fileName,int sec,int err) {
                        callback(0,err,fileName+","+sec);
                    }

                    @Override
                    public void ErrState(int errcode) {
                        callback(0,errcode,"SystemError");
                        MyLog.i("usbcamera录像SystemError"+errcode);
                        curErrorCode = errcode;
                        onDestroy();
                    }
                });

            }


        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        Log.i(TAG, "surfaceChanged: ");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        Log.i(TAG, "surfaceDestroyed: ");
        button = null;
        surfaceHolder = null;

    }


    class FloatingTouchListener implements View.OnTouchListener {
        private int x = 0;
        private int y = 0;

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = (int) motionEvent.getRawX();
                    y = (int) motionEvent.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int nowX = (int) motionEvent.getRawX();
                    int nowY = (int) motionEvent.getRawY();
                    int movedX = nowX - x;
                    int moveY = nowY - y;
                    x = nowX;
                    y = nowY;
                    layoutParams.x = layoutParams.x + movedX;
                    layoutParams.y = layoutParams.y + moveY;
                    windowManager.updateViewLayout(button, layoutParams);
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                default:
                    Log.i(TAG, "onTouch: " + motionEvent.getAction());
                    break;
            }
            return false;
        }
    }


    @Override
    public void onDestroy() {
        super.onDestroy();

        MyLog.i("onDestroy: stopservice");
//        unRegisterTestBroadReceiver();
        handler.removeCallbacks(callBackTimeOutRun);
        if (!isActive) {
            return;
        }
        isActive = false;
        if (windowManager != null) {
            windowManager.removeView(button);
        }
        if (mediaArgu != null && mediaArgu.isPush()) {
            MyLog.i(TAG, "onDestroy: 推流");
            AliSdkMgr.getInstance(FloatingService.this).destroyAliSdk();
        } else {
            MyLog.i(TAG, "onDestroy: 录像");
            if (!mediaArgu.isUsedOutCamera()/*&&mediaRecordCls != null*/) {
                /****
                // mediaRecordCls.stop()里面有回调录像结束 文件名+时长

                mediaRecordCls.stop();**************/



                CameraWrapper.getInstance().stopVideoRecord(4);


            }
            if (mediaArgu.isUsedOutCamera()){
                MyLog.i( "onDestroy:  停止本地录像");

                if (!isYourStop){
                    MyLog.i("录像要求时间未到，用户主动点击结束");
                     if (usbCameraExist){
                         UsbCameraVideo.getInstance().stopPuser(curErrorCode);

                         MyLog.i(TAG,
                                 "UsbCamera停止录像后，恢复err=4"
                         );
                         curErrorCode = 4;
                         usbCameraExist = false;

                     }else{
                         MyLog.i("UsbCamera出错，本地录像未成功");
                     }
                     isYourStop = false;
                }else{
                    MyLog.i("usb录像设置的时间到结束录像,回调");
                    UsbCameraVideo.getInstance().stopPuser(5);
                }

            }
        }



        stopSelf();
    }



    private void showwindow() {
        if (windowManager == null)
            windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        MyLog.i(TAG, "showwindow: ");
        button = new SurfaceView(this);
        surfaceHolder = button.getHolder();
        surfaceHolder.addCallback(this);
        //setType必须设置，要不出错.
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        button.setOnTouchListener(new FloatingTouchListener());
        button.setBackgroundColor(Color.TRANSPARENT);

        //设置LayoutParams
        layoutParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            Log.i(TAG, "showwindow: type_phone");
        }
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//不可获取焦点
        layoutParams.format = PixelFormat.RGBA_8888;
        layoutParams.width = 10;
        layoutParams.height = 10;
        layoutParams.x = 300;
        layoutParams.y = 300;
        //将悬浮窗添加到WindowManager
        windowManager.addView(button, layoutParams);
        Log.i(TAG, "showwindow: addview");
    }


    /*****************************以下是内部相机 新增水印功能************************************/
    private void initCamera(boolean isChecked) {
        CameraWrapper.getInstance().setScreenPort(false);

        CameraWrapper.getInstance().setRecordParams(mediaArgu);
//        changeSurfaceView(isChecked);
        CameraWrapper.getInstance()
                .setCameraId(Camera.CameraInfo.CAMERA_FACING_BACK)
                .doOpenCamera(button);
        CameraWrapper.getInstance().pausePreview();
        CameraWrapper.getInstance().startPreview();

    }
    /****************************************内部相机水印结束*************************/
}
